package com.wyq.util;

import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author zhangyun
 */
public class DateUtils extends org.apache.commons.lang.time.DateUtils {
    public static final Log log = LogFactory.getLog(DateUtils.class);
    public static String MONTH_ENAME[] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV",
        "DEC"};
    public static String DAY_CNAME[] = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
    //默认日期格式  
    private static final String[] parsePatterns = new String[] {"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd", "HH:mm",
        "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd", "HHmm", "ddMMMyy", "yyyyMMddHHmmss"
    // 这里可以增加更多的日期格式，用得多的放在前面   
    };

    /**
     * 【获取月份的数字】
     * 
     * @param monthEname 月份的英文名称
     * @param length 返回长度
     * @return 转换后的日期
     */
    public static String getMonthEnameNum(String monthEname, int length) {
        int i;
        for (i = 0; i < MONTH_ENAME.length; i++) {
            if (MONTH_ENAME[i].equals(monthEname)) {
                break;
            }
        }
        i += 1;
        String monthEnameNum = String.valueOf(i);
        if (length == 2 && monthEnameNum.length() < length) {
            monthEnameNum = "0" + monthEnameNum;
        }
        return monthEnameNum;
    }

    public static Date parseFlightDate(String dateStr, String format) {
        String yearStr = dateStr.substring(dateStr.length() - 2);
        return parseFlightDate(yearStr, dateStr, "0000", format);
    }

    /**
     * 获取unix时间错
     * 
     * @param date
     * @return
     */
    public static long getTime(Date date, boolean isEnd) {
        return resetTime(date, isEnd).getTime() / 1000;
    }

    public static Date resetTime(Date date, boolean isEnd) {
        Calendar c = DateUtils.getCalendar(date);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        return c.getTime();
    }

    /**
     * 解析航班日期
     * 
     * @param dateStr
     * @param timeStr
     * @param format
     * @return
     * @author zyun
     */
    public static Date parseFlightDate(String yearStr, String dateStr, String timeStr, String format) {
        Calendar c = null;
        int year = -1;
        String monthCode = dateStr.substring(2, 5);
        int month = Integer.parseInt(getMonthEnameNum(monthCode, 1));
        int curMonth = -1;
        if (StringUtils.isEmpty(yearStr)) {
            c = getCalendar(new Date());
            year = c.get(c.YEAR);
            curMonth = c.get(c.MONTH);
            if (month < curMonth) {
                year += 1;
            }
        } else {
            year = Integer.parseInt(yearStr);
        }
        String dayStr = dateStr.substring(0, 2);
        if (dayStr.startsWith("0")) {
            dayStr = dayStr.substring(1, 2);
        }
        String hourStr = timeStr.substring(0, 2);
        if (hourStr.startsWith("0")) {
            hourStr = hourStr.substring(1, 2);
        }
        String minuteStr = null;
        minuteStr = timeStr.substring(2, 4);
        if (minuteStr.startsWith("0")) {
            minuteStr = minuteStr.substring(1, 2);
        }
        Date flightDate = null;
        try {
            flightDate = getDate(year, monthCode, Integer.parseInt(dayStr), Integer.parseInt(hourStr),
                Integer.parseInt(minuteStr), 0);
        } catch (Exception e) {
            log.error("", e);
        }
        return flightDate;
    }

    /**
     * 使用默认的日期格式将字符串转换为日期
     * 
     * @param str 要转换的字符串
     * @return 转换后的日期
     * @throws ParseException 没有匹配的日期格式
     */
    public static Date parseDate(String str) throws ParseException {
        return parseDate(str, parsePatterns);
    }

    /**
     * 使用给定的日期格式将字符串转换为日期
     * 
     * @param str 要转换的字符串
     * @param parsePattern 日期格式字符串
     * @return 转换后的日期
     * @throws ParseException 日期格式不匹配
     */
    public static Date parseDate(String str, String parsePattern) throws ParseException {
        return parseDate(str, new String[] {parsePattern});
    }

    /**
     * @description 【获取当前日期日历】
     * @param date
     * @return
     * @author zhangyun
     */
    public static Calendar getCalendar(Date date) {
        if (date == null)
            return null;
        Calendar c = new GregorianCalendar();
        c.setTime(date);
        return c;
    }

    /**
     * @description 【date加months月】 如果要想直接用date对象，请这样调用 addMonth(getCalendar(Date date), int months)
     * @param c
     * @param months
     * @return
     * @author zhangyun
     */
    public static Date addMonth(Calendar c, int months) {
        if (c == null)
            return null;
        c.add(Calendar.MONTH, months);
        return c.getTime();
    }

    /**
     * @description 【date加days日】 如果要想直接用date对象，请这样调用 addDay(getCalendar(Date date), int days)
     * @param c
     * @param days
     * @return
     * @author zhangyun
     */
    public static Date addDay(Calendar c, int days) {
        if (c == null)
            return null;
        c.add(Calendar.DAY_OF_MONTH, days);
        return c.getTime();
    }

    /**
     * @description 【date加分钟】 如果要想直接用date对象，请这样调用 addMinutes(getCalendar(Date date), int minutes)
     * @author zhangyun
     * @param c
     * @param minutes
     * @return
     * @author zhangyun
     */
    public static Date addMinutes(Calendar c, int minutes) {
        if (c == null)
            return null;
        c.add(Calendar.MINUTE, minutes);
        return c.getTime();
    }

    /**
     * @description 【date加小时】 如果要想直接用date对象，请这样调用 addHours(getCalendar(Date date), int hours)
     * @param c
     * @param minutes
     * @return
     * @author zhangyun
     */
    public static Date addHours(Calendar c, int hours) {
        if (c == null)
            return null;
        c.add(Calendar.HOUR_OF_DAY, hours);
        return c.getTime();
    }

    /**
     * @description 【date加小时,分钟】 如果要想直接用date对象，请这样调用 addHoursAndMin(getCalendar(Date date), int hours,int minutes)
     * @param c
     * @param hours
     * @param imnutes
     * @return
     * @author zhangyun
     */
    public static Date addHoursAndMin(Calendar c, int hours, int minutes) {
        if (c == null)
            return null;
        c.add(Calendar.HOUR_OF_DAY, hours);
        c.add(Calendar.MINUTE, minutes);
        return c.getTime();
    }

    /**
     * @description 【获取一周中的第几天】
     * @param date
     * @return
     * @author zhangyun
     */
    public static int getDayOfWeek(Date date) {
        Calendar c = getCalendar(date);
        // 判断是一周的第几天 本地本地化设置为星期天开始1 星期六为7  所以-1 
        int dayOfWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
        // 星期日为7
        if (dayOfWeek == 0)
            dayOfWeek = 7;
        return dayOfWeek;
    }

    /**
     * @description 【获取一周中的星期几】
     * @param date
     * @return
     * @author zhangyun
     */
    public static String getDayOfWeekCn(Date date) {
        if (date == null)
            return null;

        // 获取一周中的第几天 0 :周日 
        int t = getDayOfWeek(date);
        if (t == 7)
            t = 0;
        return DAY_CNAME[t];
    }

    /**
     * @description 【获取当前是一周中的星期几】
     * @return
     * @author zhangyun
     */
    public static String getDayOfWeekCn() {
        return getDayOfWeekCn(new Date());
    }

    /**
     * @description 【根据月简写，日获取日期对象】
     * @param monthCode
     * @param day
     * @return
     * @author zhangyun
     */
    public static Date getDate(String monthCode, int day) {
        if (monthCode == null)
            return null;
        Calendar c = getCalendar(new Date());
        // 十二月的英文简称
        int i = 0;
        for (String monthStr : MONTH_ENAME) {
            if (monthStr.equalsIgnoreCase(monthCode)) {
                break;
            }
            i++;
        }
        c.set(Calendar.MONTH, i);
        c.set(Calendar.DATE, day);
        return c.getTime();
    }

    /**
     * @description 【根据月简写，日获取日期对象】
     * @param monthCode
     * @param day
     * @return
     * @author zhangyun
     */
    public static Date getDate(int year, String monthCode, int day) {
        if (monthCode == null)
            return null;
        Calendar c = getCalendar(new Date());
        // 十二月的英文简称
        int i = 0;
        for (String monthStr : MONTH_ENAME) {
            if (monthStr.equalsIgnoreCase(monthCode)) {
                break;
            }
            i++;
        }
        c.set(year, i, day);
        return c.getTime();
    }

    /**
     * 通过年月（英文）日小时分秒获取日期
     * 
     * @param year
     * @param monthCode
     * @param day
     * @param hourOfDay
     * @param minute
     * @param second
     * @return
     * @author zhangyun
     */
    public static Date getDate(int year, String monthCode, int day, int hourOfDay, int minute, int second) {
        if (monthCode == null)
            return null;
        Calendar c = new GregorianCalendar();
        // 十二月的英文简称
        int i = 0;
        for (String monthStr : MONTH_ENAME) {
            if (monthStr.equalsIgnoreCase(monthCode)) {
                break;
            }
            i++;
        }
        // 重置时间
        c.setTimeInMillis(0);
        c.set(year, i, day, hourOfDay, minute, second);
        return c.getTime();
    }

    public static Date getCalendarDate(final int day, final int month, final int year) {
        final Calendar calendar = Calendar.getInstance();
        calendar.set(year, month, day);
        final Date date = calendar.getTime();
        return date;
    }

    /**
     * @description 【是否是闰年】
     * @param year
     * @return
     * @author zhangyun
     */
    public static boolean isLeapYear(int year) {
        GregorianCalendar gc = new GregorianCalendar();
        return gc.isLeapYear(year);
    }

    /**
     * @description 【util.date->sql.date】
     * @param date
     * @return
     * @author zhangyun
     */
    public static java.sql.Timestamp utilDate2SqlDate(java.util.Date date) {
        if (date == null)
            return null;
        Calendar c = getCalendar(date);
        java.sql.Timestamp sqlDate = new java.sql.Timestamp(c.getTimeInMillis());
        return sqlDate;
    }

    /**
     * @description 【获取未知类型的Timestamp】
     * @param value
     * @return
     * @author zhangyun
     */
    public static Timestamp getTimestamp(Object value) {
        if (value == null)
            return null;
        Timestamp timestamp = null;
        if (value instanceof Timestamp) {
            timestamp = (Timestamp)value;
        } else {
            Class clz = value.getClass();
            Method m = null;
            try {
                m = clz.getMethod("timestampValue", null);
                timestamp = (Timestamp)m.invoke(value, null);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                log.error("", e);
            }
        }
        return timestamp;
    }

    /**
     * @description 【获取时间间隔分钟】
     * @param minDate
     * @param maxDate
     * @return
     * @author zhangyun
     */
    public static double getIntervalMinutes(Date minDate, Date maxDate) {
        double days = 0.0;
        if (minDate == null || maxDate == null) {
            return days;
        }
        try {
            long interval = maxDate.getTime() - minDate.getTime();
            days = Double.valueOf(interval) / 1000 / 60;
        } catch (Exception e) {
            log.error("", e);
        }
        return days;
    }

    /**
     * @description 【获取时间间隔小时】
     * @param minDate
     * @param maxDate
     * @return
     * @author zhangyun
     */
    public static double getIntervalHours(Date minDate, Date maxDate) {
        double days = 0.0;
        if (minDate == null || maxDate == null) {
            return days;
        }
        try {
            days = getIntervalMinutes(minDate, maxDate) / 60;
        } catch (Exception e) {
            log.error("", e);
        }
        return days;
    }

    /**
     * @description 【校验是否隔夜】
     * @param startTime
     * @param endTime
     * @author zhangyun
     * @return
     */
    public static boolean checkIsIntervalDay(String startTime, String endTime, String format) {
        boolean isIntervalDay = false;
        if (parsePatterns[2].equals(format) && "00:00".compareTo(endTime) < 0 && "12:00".compareTo(endTime) >= 0
            && "12:00".compareTo(startTime) < 0 && "23:59".compareTo(startTime) >= 0) {
            isIntervalDay = true;
        } else if (parsePatterns[5].equals(format) && "0000".compareTo(endTime) < 0 && "1200".compareTo(endTime) >= 0
            && "1200".compareTo(startTime) < 0 && "2359".compareTo(startTime) >= 0) {
            isIntervalDay = true;
        } else {
            log.error(startTime + " " + endTime + " " + format);
        }
        return isIntervalDay;
    }

    /**
     * @description 【获取时间间隔天】
     * @param minDate
     * @param maxDate
     * @return
     * @author zhangyun
     */
    public static double getIntervalDays(Date minDate, Date maxDate) {
        double days = 0;
        if (minDate == null || maxDate == null) {
            return days;
        }
        try {
            days = getIntervalHours(minDate, maxDate) / 24;
        } catch (Exception e) {
            log.error("", e);
        }
        return days;
    }

    public static void main(String[] args) {
        /*String   s2   =   "2005-10-31 10:23:11";
        SimpleDateFormat   sdf   =   new   SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); 
        Date d1 = null;
        try {
        	d1 = sdf.parse(s2);
        } catch (ParseException e) {
        	// TODO Auto-generated catch block
        	log.error("",e);
        } 
        System.out.println(d1);
        System.out.println(utilDate2SqlDate(d1));*/
        // 判断是一周的第几天 星期天开始1 星期六为7
        Calendar c = getCalendar(new Date());
        int dayOfWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
        System.out.println("getDayOfWeek(new Date())=========" + c.get(Calendar.DAY_OF_WEEK));

        System.out.println("getDayOfWeekCn(new Date())=========" + getDayOfWeekCn());
        System.out.println("new Date()=========" + new Date());
        Calendar gc = new GregorianCalendar();
        Date tomorrow = addDay(gc, 1);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date tomorrow2 = null;
        try {
            tomorrow2 = sdf.parse(sdf.format(tomorrow));
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            log.error("", e);
        }
        System.out.println(sdf2.format(tomorrow2));

    }

    /**
     * @description 【取得当前日期】 默认格式 yyyy-MM-dd HH:mm:ss,如果格式错误,直接返回new Date
     * @return String
     * @createTime 2010-7-23 下午02:06:50
     * @author wang-wl
     */
    public static Date getCurrentDate() {
        // 当前时间
        Date date = new Date();
        try {
            //默认格式
            String format = "yyyy-MM-dd HH:mm:ss";
            SimpleDateFormat sdf = new SimpleDateFormat(format);

            String dateStr = DateFormatUtils.format(new Date(), format);
            date = sdf.parse(dateStr);
        } catch (ParseException e) {

            log.error("", e);
            date = new Date();
        }
        return date;
    }

    /**
     * @description 【取得当前日期】
     * @param format
     * @return
     * @createTime 2010-7-23 下午03:01:53
     * @author wang-wl
     * @throws ParseException
     */
    public static Date getCurrentDate(String format) throws ParseException {
        // 默认格式 yyyy-MM-dd
        return String2Date(getCurrentDateStr(format), format);
    }

    /**
     * @description 【取得当前日期】 默认格式 yyyy-MM-dd HH:mm:ss
     * @return String
     * @createTime 2010-7-23 下午02:06:50
     * @author wang-wl
     */
    public static String getCurrentDateStr() {
        // 默认格式 yyyy-MM-dd
        String format = "yyyy-MM-dd";
        return getCurrentDateStr(format);
    }

    /**
     * @description 【得到当前的时间】精确到毫秒，格式为：hh:mm:ss
     * @return Date
     * @createTime 2010-7-23 下午02:06:50
     * @author wang-wl
     */
    public static String getCurrentTimeStr() {
        // 默认格式 yyyy-MM-dd
        String format = "HH:mm:ss";
        return getCurrentDateStr(format);
    }

    /**
     * @description 【取得当前日期】
     * @return String
     * @createTime 2010-7-23 下午02:06:50
     * @author wang-wl
     */
    public static String getCurrentDateStr(String format) {
        // 按格式取得时间
        return DateFormatUtils.format(new Date(), format);
    }

    /**
     * @description 【字符转化为时间】
     * @param dateStr
     * @param format
     * @return
     * @createTime 2010-7-23 下午02:38:17
     * @author wang-wl
     * @throws ParseException
     */
    public static Date String2Date(String dateStr) throws ParseException {
        //默认格式
        String format = "yyyy-MM-dd HH:mm:ss";
        return String2Date(dateStr, format);
    }

    /**
     * @description 【字符转化为时间】
     * @param dateStr
     * @param format
     * @return
     * @createTime 2010-7-23 下午02:38:17
     * @author wang-wl
     * @throws ParseException
     */
    public static Date String2Date(String dateStr, String format) throws ParseException {
        if (StringUtils.isEmpty(dateStr)) {
            return null;
        }

        // 格式化时间
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date date = sdf.parse(dateStr);

        return date;
    }

    /**
     * @description 【转化为Timestamp】
     * @param dateStr
     * @return
     * @createTime 2010-7-23 下午02:39:12
     * @author wang-wl
     * @throws ParseException
     */
    public static Timestamp Date2Timestamp(String dateStr) throws ParseException {
        if (StringUtils.isEmpty(dateStr)) {
            return null;
        }
        // 转化为日期格式后转化为转化为Timestamp
        String format = "yyyy-MM-dd HH:mm:ss";
        Date date = String2Date(dateStr, format);

        return Date2Timestamp(date);
    }

    /**
     * @description 【转化为Timestamp】
     * @param date
     * @return
     * @createTime 2010-7-23 下午02:39:12
     * @author wang-wl
     */
    public static Timestamp Date2Timestamp(Date date) {
        if (null == date) {
            return null;
        }
        // 格式化日期 精确到秒
        String dateStr = DateFormatUtils.format(date, "yyyy-MM-dd HH:mm:ss");
        return Timestamp.valueOf(dateStr.toString());
    }

    /**
     * @description 【获取日期区间】
     * @param type
     * @return
     * @author wyh
     * @modify by zhangyun 修改部分写法
     */
    public static List<Date> getDatePeriod(int type) {
        // 返回时间段
        List<Date> list = new ArrayList<Date>();
        // 当前时间
        Date nowDate = DateUtils.getCurrentDate();
        // 获取当前时间日历
        Calendar calendar = DateUtils.getCalendar(nowDate);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        // 开始时间
        Date startTime = null;
        // 结束时间
        Date endTime = null;
        switch (type) {
        // 当天
            case 1:
                endTime = calendar.getTime();
                startTime = calendar.getTime();
                break;
            // 前三天
            case 2:
                endTime = calendar.getTime();
                startTime = DateUtils.addDay(calendar, -3);
                break;

            // 本周内
            case 3:
                int dayOfWeek = DateUtils.getDayOfWeek(nowDate);
                int endDateNum = 7 - dayOfWeek;
                endTime = DateUtils.addDay(calendar, endDateNum);
                startTime = DateUtils.addDay(calendar, -6);
                break;
            // 最近一个月
            case 4:
                endTime = calendar.getTime();
                startTime = DateUtils.addMonth(calendar, -1);
                break;
            // 最近三个月
            case 5:
                endTime = calendar.getTime();
                startTime = DateUtils.addMonth(calendar, -3);
                break;
            // 最近1年
            case 6:
                endTime = calendar.getTime();
                //startTime = DateUtils.addYears(nowDate, -1);
                break;
        }
        list.add(startTime);
        list.add(endTime);
        return list;
    }

    //------栾晓东新添方法！
    /**
     * 用于返回指定日期格式的日期增加指定天数的日期
     * 
     * @param date 指定日期
     * @param format 指定日期格式
     * @param days 指定天数
     * @return 指定日期格式的日期增加指定天数的日期
     */
    public static String getFutureDay(Date date, String format, int days) {
        String future = "";
        try {
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
            calendar.setTime(date);
            calendar.add(Calendar.DATE, days);
            date = calendar.getTime();
            future = simpleDateFormat.format(date);
        } catch (Exception e) {

        }

        return future;
    }

    public static String getNextDay(Date date, String format, int days) {
        String future = "";
        try {
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
            calendar.setTime(date);
            date = calendar.getTime();
            future = simpleDateFormat.format(date);
        } catch (Exception e) {

        }

        return future;
    }
}
